/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.fyx.web.context;

import java.util.Collection;
import java.util.Map;
import java.util.Observer;
import java.util.Set;
import java.util.logging.Logger;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;
import org.fyx.secure.ejb.FyxContext;
import org.fyx.core.context.FyxContextFactory;
import org.fyx.core.web.event.MenuCreatingEventHandler;
import org.fyx.core.web.event.RoleCreatingEventHandler;
import org.fyx.linker.web.category.LinkerEdit;
import org.fyx.mula.ejb.IsoLanguage;
import org.fyx.secure.entity.SecureUser;
import org.primefaces.component.menuitem.MenuItem;
import org.primefaces.model.MenuModel;

/**
 * Hlavní webový kontext.
 * Udržuje veškeré informace vztahující se ke konkrítnímu klientu jako jsou
 * jeho uzivatelska opravneni, nastaveni jazyka, aktualni URL, ...
 * <p>
 * Trida je zaroven anotovana jako managed beana, aby k ni byl pristup
 * i primo z JSF stranek.
 * 
 * @author xljan
 */
@ManagedBean
@RequestScoped
public class WebContext extends FyxContext implements Cloneable {

    /**
     * Nazev promenne v session mape JSF.
     */
    public static final String SESSION_KEY = "__session";
    private static final RoleCreatingEventHandler roleCreatingEventHandler =
            new RoleCreatingEventHandler();
    private static final MenuCreatingEventHandler menuCreatingEventHandler =
            new MenuCreatingEventHandler();

    /**
     * Vrati objekt typu {@link Session}m ktery je ulozen v externim kontextu
     * faces pod klicem {@link WebContext#SESSION_KEY}.
     * 
     * @return 
     */
    protected static Session getSession() {
        Session session = (Session) FacesContext.getCurrentInstance().
                getExternalContext().getSessionMap().get(SESSION_KEY);
        if (session == null) {
            session = new Session();
            FacesContext.getCurrentInstance().getExternalContext().
                    getSessionMap().put(SESSION_KEY, session);
        }
        return session;
    }

    /**
     * Vrati aktualni kontext klienta.
     * 
     * @return kontext klienta.
     */
    public static WebContext getCurrentContext() {
        return (WebContext) FyxContextFactory.getContext();
    }

    @Override
    public SecureUser getUser() {
        return getSession().getUser();
    }

    @Override
    protected void setUser(SecureUser user) {
        getSession().setUser(user);
    }

    @Override
    public boolean isUserInRole(String role) {
        return getSession().getRoles().contains(role);
    }

    @Override
    protected void setUserRoles(Set<String> roles) {
        getSession().setRoles(roles);
    }

    @Override
    protected Set<String> getUserRoles() {
        return getSession().getRoles();
    }

    @Override
    public boolean isLogedIn() {
        return getSession().isLogedIn();
    }

    @Override
    protected void setLogedIn(boolean logedIn) {
        getSession().setLogedIn(logedIn);
    }

    @Override
    public String getIsoLanguage() {
        return getSession().getIsoLanguage();
    }

    @Override
    public Logger getLogger(String name) {
        return Logger.getLogger(name);
    }

    /**
     * Nastavi iso jazyka pro aktualniho klienta. Tyto zkratky jsou
     * definovany v interface {@link org.fyx.mula.ejb.IsoLanguage}.
     * 
     * @param isoLanguage trimistny iso kod jazyka
     */
    public void setIsoLanguage(String isoLanguage) {
        getSession().setIsoLanguage(isoLanguage);
    }

    /**
     * Vrati zakladni URL systemu, na ktere se nachazi uvodni strana.
     * 
     * @return zakladni URL
     */
    public String getBaseUrl() {
        return getSession().getBaseUrl();
    }

    /**
     * Nastavi za zakladni URL systemu, na ktere se nachazi uvodni strana.
     * 
     * @param baseUrl zakladni url systemu
     */
    public void setBaseUrl(String baseUrl) {
        getSession().setBaseUrl(baseUrl);
    }
    
    /**
     * Vrati korenovou URL systemu, ktera neni zpracovavana jako JSF. 
     * Jedna se tedy predevsim o adresy stylu, javascript atd.
     * 
     * @return URL bez zpracovani JSF
     */
    public String getBaseNoFacesUrl() {
        return getSession().getBaseNoFacesUrl();
    }

    /**
     * Nastavi korenovou URL systemu, ktera neni zpracovavana jako JSF. 
     * Jedna se tedy predevsim o adresy stylu, javascript atd.
     * 
     * @param noFacesUrl URL bez zpracovani JSF
     */
    public void setBaseNoFacesUrl(String noFacesUrl) {
        getSession().setBaseNoFacesUrl(noFacesUrl);
    }

    /**
     * Vrati cestu k sablone s obsahem neclenenym do sloupcu.
     * 
     * @return cesta k sablone
     */
    public String getSkin0Culomns() {
        return getSession().getSkin0Culomns();
    }

    /**
     * Nastavi cestu k sablone s obsahem neclenenym do sloupcu.
     * 
     * @param skin0Culomns cesta k sablone
     */
    public void setSkin0Culomns(String skin0Culomns) {
        getSession().setSkin0Culomns(skin0Culomns);
    }

    /**
     * Vrati cestu do adresare s vzhledem. Nezamenovat s cestou
     * k sablonam modulu {@link WebContext#getTplPatch()}.
     * 
     * @return cesta k vzhledu
     */
    public String getSkinPatch() {
        return getSession().getSkinPatch();
    }

    /**
     * Nastavi cestu adresare s vzhledem. Nezamenovat s cestou
     * k sablonam modulu {@link WebContext#getTplPatch()}.
     * 
     * @param skinPatch cesta adresare s vzhledem
     */
    public void setSkinPatch(String skinPatch) {
        getSession().setSkinPatch(skinPatch);
    }

    /**
     * Vrati url adresu k aktualimu vzhledu.
     * Napr.: http://www.fyx.org/skin/base/
     * 
     * @return url adresa k aktualnimu vzhledu
     */
    public String getSkinUrl() {
        return getSession().getSkinUrl();
    }

    /**
     * Nastavi url adresu k aktualimu vzhledu.
     * Napr.: http://www.fyx.org/skin/base/
     * 
     * @param skinUrl url adresa k aktualnimu vzhledu
     */
    public void setSkinUrl(String skinUrl) {
        getSession().setSkinUrl(skinUrl);
    }

    /**
     * Vrati cestu adresare k sablonam modulu.
     * Napr.: /templates/
     * 
     * @return cesta k sablonam modulu
     */
    public String getTplPatch() {
        return getSession().getTplPatch();
    }

    /**
     * Vrati cestu adresare k sablonam modulu.
     * 
     * @return cesta k sablonam modulu
     */
    public void setTplPatch(String tplPatch) {
        getSession().setTplPatch(tplPatch);
    }

    /**
     * Vrati url adresu pro pristup k sablonam modulu.
     * Napr.: http://www.fyx.org/faces/templates/
     * 
     * @return url adresa k sablonam modulu
     */
    public String getTplUrl() {
        return getSession().getTplUrl();
    }

    /**
     * Nastavi url adresu pro pristup k sablonam modulu.
     * Napr.: http://www.fyx.org/faces/templates/
     * 
     * @param tplUrl url adresa k sablonam modulu
     */
    public void setTplUrl(String tplUrl) {
        getSession().setTplUrl(tplUrl);
    }

    /**
     * Vrati potomka tridy {@link java.util.Observable} ktery uchovava
     * observery realizujici {@link java.util.Observer}, kteri pozoruji
     * udalost tvoreni menu.
     * 
     * @return 
     */
    public static MenuCreatingEventHandler getMenuCreatingEventHandler() {
        return menuCreatingEventHandler;
    }

    /**
     * Vrati potomka tridy {@link java.util.Observable} ktery uchovava
     * observery realizujici {@link java.util.Observer}, kteri pozoruji
     * udalost tvoreni menu.
     * 
     * @return 
     */
    public RoleCreatingEventHandler getRoleCreatingEventHandler() {
        return roleCreatingEventHandler;
    }

    /**
     * Vrati mapu {@link MenuItem}. Kde klic je id - {@link MenuItem#getId()}.
     * V teto mape jsou pouze odkazy na ktere ma aktualni uzivatel opravneni.
     * <p>
     * Vsechny odkazy se ziskaji metodou {@link WebContext#getMapAllMenuItems()}
     * 
     * @return mapa odkazu
     */
    public static Map<String, MenuItem> getMapMenuItems() {
        return getSession().getMapMenuItems();
    }

    /**
     * Vrati mapu {@link MenuItem}. Kde klic je id - {@link MenuItem#getId()}.
     * V teto mape jsou vsechny odkazy vcetne tech na ktere nema aktualni 
     * uzivatel opravneni.
     * 
     * @return mapa odkazu
     */
    public static Map<String, MenuItem> getMapAllMenuItems() {
        return getSession().getMapAllMenuItems();
    }

    /**
     * Vrati aktualne vytvoreny model viceurovnoveho menu. Model se vytvari
     * pri volani observeru udalosti {@link MenuCreatingEventHandler}.
     * <p>
     * Konkretni tvorba menu je v {@link LinkerEdit}.
     * 
     * @return model viceurovnoveho menu
     */
    public static MenuModel getMenuModel() {
        return getSession().getMenuModel();
    }

    /**
     * Nastavi model viceurovnoveho menu.
     * 
     * @param menuModel model viceurovnoveho menu
     */
    public static void setMenuModel(MenuModel menuModel) {
        getSession().setMenuModel(menuModel);
    }

    /**
     * Vrati kontejner se zpravami ktere se zobrazi po presmerovani na
     * jinou URL adresu. Pouziva se zejmena pro zobrazeni zprav po
     * volani funkci {@link WebPage#redirect(java.lang.String)} nebo
     * {@link WebPage#refresh()}
     * 
     * @return kontejner se zpravami
     */
    public static Collection<FacesMessage> getMessages() {
        return getSession().getMessages();
    }

    /**
     * Vrati aktualni URL adresu. Napr.: 
     * http://localhost:8080/FyxWeb/faces/templates/cms/show.xhtml?p1=1
     * 
     * @return aktualni URL uzivatele
     */
    public static String getRequestURL() {
        HttpServletRequest request = (HttpServletRequest) FacesContext.
                getCurrentInstance().getExternalContext().getRequest();
        String queryString = (request.getQueryString() != null) ?
                "?" + request.getQueryString() : "";
        return ((HttpServletRequest) request).getRequestURL() + queryString;
    }

    public static String getCurrentUrl() {
        return getSession().getCurrentUrl();
    }

    public static void setCurrentUrl(String url) {
        getSession().setCurrentUrl(url);
    }
}
